package ranab.io;

import java.io.*;

/**
 * Do something on files recursively. 
 * Assumption : root exists.
 * 
 * @author <a href="mailto:rana_b@yahoo.com">Rana Bhattacharyya</a>
 */

public class FileNavigator implements Runnable {
    
    private File mTopFile;
    private FileAction mAction; 
    private boolean mbThreaded;
    private boolean mbStopRequest;
    
    /**
     * Constructors.
     * @param top root directory
     * @action action to be done on each file.
     */
    public FileNavigator(File top, FileAction action) {
        this(top, action, false);
    }
    
    public FileNavigator(File top, FileAction action, boolean threaded) {
        if( (top == null) || (action == null) ) {
            throw new NullPointerException();
        }
        mTopFile = top;
        mAction = action;
        mbThreaded = threaded;
    }
    
    
    /**
     * Start navigating the directory tree.
     */
    public void navigate() {
        if(mbThreaded) {
            new Thread(this).start();
        }
        else {
            run();
        }
    } 
    
    
    /**
     * Thread starting point.
     */
    public void run() {
       
       // check top file object 
       if(!mTopFile.exists()) {
           return;
       }
       mAction.startAction();
       navigateFile(mTopFile);
       mAction.endAction();
    }
    
    /**
     * Recursively touch files.
     */
    private void navigateFile(File fl) {
        
        // stop request
        if(mbStopRequest) {
            return;
        }
        
        // touch children recursively
        if(fl.isDirectory()) {
            File fileList[] = fl.listFiles();
            for(int i=0; i<fileList.length; i++) {
                if(mbStopRequest) {
                    return;
                }
                navigateFile(fileList[i]);
            }
        }
        
        // now touct the current file
        mAction.actionPerformed(fl);
    }
    
    /**
     * Stop navigation.
     */
    public void stopNavigation() {
        mbStopRequest = true;
    }
}